﻿using MediatR;
using Microsoft.Extensions.Options;
using Sgr.Application;
using Sgr.Application.Commands;
using Sgr.Identity;
using Sgr.Identity.Services;

namespace Sgr.Indentity.Application.Commands
{
    /// <summary>
    /// 注销命令处理器
    /// </summary>
    public class LogoutCommandHandle :
        IdentityCommandHandleBase,
        IRequestHandler<LogoutCommand, CommandResult<bool>>
    {
        private readonly IdentityOptions _identityOptions;
        private readonly ISignatureChecker _signatureChecker;
        private readonly ITokenBlacklistService _tokenBlacklistService;

        public LogoutCommandHandle(
            IAccountAuthService accountService,
            IHttpContextAccessor httpContextAccessor,
            ISignatureChecker signatureChecker,
            ITokenBlacklistService tokenBlacklistService,
            IOptions<IdentityOptions> options)
            : base(accountService, httpContextAccessor)
        {
            _identityOptions = options?.Value ?? throw new ArgumentNullException(nameof(options));
            _signatureChecker = signatureChecker ?? throw new ArgumentNullException(nameof(signatureChecker));
            _tokenBlacklistService = tokenBlacklistService ?? throw new ArgumentNullException(nameof(tokenBlacklistService));
        }

        public async Task<CommandResult<bool>> Handle(LogoutCommand request, CancellationToken cancellationToken)
        {
            // 参数验证
            Check.NotNull(request, nameof(request));
            Check.StringNotNullOrEmpty(request.AccessToken, nameof(request.AccessToken));

            // 签名验证
            if (_identityOptions.UseSignature)
            {
                string secretKey = request.AccessToken!;
                if (!_signatureChecker.VerifySignature(request.Signature, request.Timestamp, request.Nonce, secretKey, secretKey))
                    return CommandResult.Invalid<bool>("请求参数无效!");
            }

            // 提取令牌相关信息
            var jwtToken = GetJwtTokenFromAccessToken(request.AccessToken ?? "");
            if (jwtToken == null)
            {
                return CommandResult.Invalid<bool>("令牌无效！可能原因包括：令牌为空或格式错误!");
            }

            // JWT TOKEN 添加至黑名单
            await AddTokenToBlacklistAsync(_tokenBlacklistService, jwtToken, _identityOptions.JWT);

            // 移除刷新令牌
            HttpRequest? httpRequest = _httpContextAccessor?.HttpContext?.Request;

            var userId = jwtToken.Claims.FirstOrDefault(c => c.Type == Constant.CLAIM_USER_ID)?.Value;
            if (!string.IsNullOrEmpty(userId) && httpRequest != null)
            {
                string name = _identityOptions.JWT.RefreshTokenCookieName ?? "refreshToken";
                if (httpRequest.Cookies.TryGetValue(name, out var oldRefreshToken))
                {
                    await _accountService.RemoveRefreshTokenAsync(userId, oldRefreshToken, cancellationToken);

                    // 清除刷新令牌 Cookie
                    var cookieOptions = new CookieOptions
                    {
                        HttpOnly = true,
                        Secure = _identityOptions.JWT.RefreshTokenSecure,                                           // 生产环境中应启用 HTTPS
                        SameSite = HttpCookieOptions.ToSameSiteMode(_identityOptions.JWT.RefreshTokenSameSite),     // 根据需求设置
                        Expires = DateTimeOffset.UtcNow.AddMinutes(_identityOptions.JWT.RefreshTokenExpireMinutes)        // 设置适当的过期时间
                    };

                    if (!string.IsNullOrEmpty(_identityOptions.JWT.RefreshTokenDomain))
                    {
                        cookieOptions.Domain = _identityOptions.JWT.RefreshTokenDomain;
                    }

                    if (!string.IsNullOrEmpty(_identityOptions.JWT.RefreshTokenPath))
                    {
                        cookieOptions.Path = _identityOptions.JWT.RefreshTokenPath;
                    }

                    _httpContextAccessor?.HttpContext?.Response?.Cookies?.Delete(name, cookieOptions);
                }
            }

            return CommandResult.Success(true, "注销成功");
        }

        ///// <summary>
        ///// 解析SameSite模式
        ///// </summary>
        //private static SameSiteMode ParseSameSiteMode(string sameSite)
        //{
        //    return sameSite?.ToLower() switch
        //    {
        //        "strict" => SameSiteMode.Strict,
        //        "lax" => SameSiteMode.Lax,
        //        "none" => SameSiteMode.None,
        //        _ => SameSiteMode.Lax // 默认使用Lax模式
        //    };
        //}
    }
}